package main

import (
	"fmt"
	"sync"
	"time"
	"unsafe"
)

type GoLimit struct {
	n int
	c chan struct{}
}

// initialization GoLimit struct
func New(n int) *GoLimit {
	return &GoLimit{
		n: n,
		c: make(chan struct{}, n), // chan struct{} 内存占用为 0
	}
}

// Run f in a new goroutine but with limit.
func (g *GoLimit) Run(f func()) {
	g.c <- struct{}{}
	go func() {
		f()
		<-g.c
	}()
}

var wg = sync.WaitGroup{}

func main() {
	number := 10
	g := New(5)
	for i := 0; i < number; i++ {
		wg.Add(1)
		value := i
		goFunc := func() {
			// 做一些业务逻辑处理
			fmt.Printf("go func: %d\n", value)
			time.Sleep(time.Second)
			wg.Done()
		}
		g.Run(goFunc)
	}
	wg.Wait()
	fmt.Println("unsafe.Sizeof(struct{}{}): ", unsafe.Sizeof(struct{}{}))
	fmt.Println("unsafe.Sizeof(true): ", unsafe.Sizeof(true))
}
